<!DOCTYPE HTML>
<html lang="en">
<head>
  <link rel="icon" type="image/png" href="../../manual/favicon-checkerframework.png">
  <meta charset="utf-8">
  <title>Checker Framework release process</title>
  <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
  <script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
  <style type="text/css">
    .page-header {
    padding-left: 10px;
    margin-left: 10px;
    }

    .container {
    padding-left: 10px;
    margin-left: 10px;
    }

    .file_layout_table th {
    background: #EFEFEF;
    }

    ul.step_list li {
    margin-top: 10px;
    }

    ul#backing_out_steps li {
    padding-bottom: 10px;
    }
  </style>
</head>

<body>
<div class="page-header">
  <h1>Release Process: Checker Framework</h1> <!-- omit from toc -->
</div>

<div class="container">
<div class="row" style="width: 100%">
<div id="content">
<p>
  This document explains how to make a release of the Checker Framework.
The process takes around 2 hours (including manual steps) when all goes according to plan.
  However, the lengthiest steps are automatic so you will be able to work on other tasks.
</p>

<div class="alert alert-success">
  <strong>Note:</strong> If you have never read this document before, please read
  the section <a href="#pre_release_checklist">Pre-release Checklist</a> first.
  It is also recommended that you read sections  <a href="#release_process_overview">Release Process Overview</a>
  and <a href="#changelog_guide">Changelog Guidelines</a> to familiarize yourself
  with the process.
</div>

<p>Contents:</p>
<!-- start toc.  do not edit; run html-update-toc instead -->
    <ul>
      <li><a href="#step_by_step">Step by Step</a></li>
      <li><a href="#continuous-integration">Continuous integration tests</a></li>
      <li><a href="#maven_local">Deploy to local Maven repository</a></li>
      <li><a href="#snapshot_release">Snapshot release</a>
        <ul>
          <li><a href="#using_snapshot_release">Using a snapshot release</a>
            <ul>
              <li><a href="#using_snapshot_release_gradle_groovy">Gradle Groovy (<code>build.gradle</code> file)</a></li>
              <li><a href="#using_snapshot_release_gradle_kotlin">Gradle Kotlin (<code>build.gradle.kts</code> file)</a></li>
              <li><a href="#using_snapshot_release_maven">Maven (<code>pom.xml</code> file)</a></li>
            </ul></li>
        </ul></li>
      <li><a href="#pre_release_checklist">Pre-release Checklist</a></li>
      <li><a href="#release_process_overview">Release Process Overview</a>
        <ul>
          <li><a href="#file_layout">File Layout</a></li>
          <li><a href="#release_scripts">Release Scripts</a></li>
        </ul></li>
      <li><a href="#changelog_guide">Changelog Guidelines</a>
        <ul>
          <li><a href="#content_guidelines">Content Guidelines</a></li>
          <li><a href="#style_guidelines">Style Guidelines</a></li>
        </ul></li>
      <li><a href="#backing_out">Backing Out an Uncommitted Release</a>
        <ul>
          <li><a href="#backing_out_steps">Manual Steps to Back Out a Release</a></li>
        </ul></li>
      <li><a href="#future_improvements">Future Improvements</a></li>
    </ul>
<!-- end toc -->


<h2 id="step_by_step">Step by Step</h2>

<p>
  More information about the steps is
  provided in the code comments of the <code>main()</code> functions of the <code>release_build</code>
  and <code>release_push</code> scripts. Please read those comments if you have never done so before.
</p>

<p>
Answering 'no' to a prompt does not exit the script unless otherwise indicated.
</p>

<p>
Be sure to carefully read all instructions on the command-line before answering 'yes' to a prompt.
This is because the scripts do not ask you to say 'yes' after each step, so you may
miss a step if you only read the paragraph asking you to say 'yes'.
</p>

<ol>
  <li>If you have never made a release before, follow the instructions in the
    <a href="#pre_release_checklist">Pre-release Checklist</a>.
  </li>
  <li>
    <b>Update stubparser.</b> If there has been
    a <a href="https://github.com/javaparser/javaparser/releases">JavaParser
    release</a> since the last Checker Framework
    release, <a href="https://github.com/typetools/stubparser#updating-from-upstream-javaparser">update
      Stubparser from JavaParser</a>.
    Do this on your own computer; it doesn't have to be done on the CSE file system..
  </li>
  <li>On your own computer, update the Checker Framework source code <em>in the <code>master</code> branch</em>:
    <ul>
      <li>
        <b>Update the AWS Java SDK BOM dependency.</b> In file <code>checker/build.gradle</code>,
        edit the <code>com.amazonaws:aws-java-sdk-bom</code> dependency to be the latest version
        number at
        <a href="https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk">https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk</a>.
        (The next time Dependabot opens a pull request for that dependency, you
        might need to respond <code>@dependabot ignore this dependency</code> to
        prevent such pull requests for the next month.)
      </li>
      <li>
        <b>Update Checker Framework change log</b> by following the instructions
        at <a href="#content_guidelines">content guidelines</a>.
      </li>
      <li> <b>Update the Checker Framework version number</b>
        in <code>checker-framework/release.gradle</code>,
        in the <code>ext</code> block.

        <p>
        Update the minor version (middle number in the version number)
        if there are any incompatibilities with the previous version.
        This includes incompatibilities for people who are maintaining a checker,
        which happens if the signature changes for any method in these classes:
        </p>
<!-- Add other classes to this list if relevant. -->
<pre>
AnnotatedTypeFactory
BaseAnnotatedTypeFactory
GenericAnnotatedTypeFactory
CFTransfer
CFAbstractTransfer
CFAbstractAnalysis
CFAnalysis
CFAbstractStore
CFStore
CFAbstractValue
CFValue
BaseTypeVisitor
BaseTypeChecker
SourceChecker
MultigraphQualifierHierarchy
AbstractQualifierPolymorphism
AnnotationUtils
TreeAnnotator
</pre>
        <p>
        (TODO: Write a command that diffs these classes between the previous and current release.)
        </p>
        <p>
        A rule of thumb is that any framework change that requires changes to more than one type-checker should be at least a minor version (middle number in the version number) bump.
        </p>
      </li>
      <li>
        <b>Commit and push</b> these changes to typetools/master.
      </li>
    </ul>
  <li>
      <strong>Log into a machine on the CSE file system, such as tern.</strong><br/>
      <code>ssh $USER@tern.cs.washington.edu<br/></code>
  </li>
  <li>
      <strong>In a user-specific temporary directory, clone/update the Checker Framework repository (it contains the release scripts).</strong><br/>
      <!-- This isn't a <pre> block because that formats differently than commands. -->
      <code>mkdir -p /scratch/$USER/cf-release<br/></code>
      <code>chown -R :types_www /scratch/$USER/cf-release<br/></code>
      <code>chmod -R g+rw /scratch/$USER/cf-release<br/></code>
      <code>cd /scratch/$USER/cf-release<br/></code>
      <code>test -d checker-framework && (cd checker-framework && git pull --ff-only --quiet) || git clone --quiet https://github.com/typetools/checker-framework.git<br/></code>
      <code>cd checker-framework/docs/developer/release<br/></code>
    (The release scripts will checkout and build all dependencies.)
  </li>
  <li><strong>Run release_build</strong> to create the release artifacts and place them in the development website<br/>
      <code>git pull && python3 release_build.py</code><br/><br/>
      For verbose debugging output, use the <code>--debug</code> option.<br/><br/>
  </li>
  <li>
      <strong>Run release_push</strong> to run a few tests and move release artifacts from the development website to the live site and to Maven Central <br/>
      <code>python3 release_push.py release</code><br/><br/>
      <div class="alert alert-danger">
        <strong>Note:</strong> The &quot;<strong>release</strong>&quot; argument states that you intend
        to do an actual release.  If you just want to test the script, leave out &quot;release&quot;
        and the script will run but not update anything.
      </div>

      If you get an obscure error about permissions, try running the release_push script several times
      in a row. This will sometimes update the repository permissions such that the script can proceed
      further each time.
  </li>
  <li> <strong>Update list of qualifiers in Project Lombok.</strong>
    Follow the instructions in <a href="https://github.com/projectlombok/lombok/blob/master/src/core/lombok/core/handlers/HandlerUtil.java#L108">HandlerUtil.java</a>.
    If the release did not add, remove, or rename any type qualifiers, no changes are required.
    Those instructions do not work on macOS, so you may need to use a Linux machine to make the changes.
  </li>
  <li> <strong>Make Daikon use the latest Checker Framework version.</strong>

    Follow the  instructions in
    <a href="https://github.com/codespecs/daikon/blob/master/java/lib/README">java/lib/README</a> to update the Checker Framework version number in Daikon.
  </li>
</ol>

  <h2 id="continuous-integration">Continuous integration tests</h2>

  <p>
    The following continuous integration tests should all pass before you make changes that you need to test.  If not, notify the
    relevant team members.  Refresh this page to see the latest status.
  </p>

  <ul>
    <li>Checker Framework: <a href="https://dev.azure.com/checkerframework/checkerframework/_build/latest?definitionId=5&branchName=master"><img src="https://dev.azure.com/checkerframework/checkerframework/_apis/build/status%2Ftypetools.checker-framework?branchName=master" alt="Azure Pipelines typetools/checker-framework status"></a></li>
    <li>JDK: <a href="https://dev.azure.com/checkerframework/checkerframework/_build/latest?definitionId=6&branchName=master"><img src="https://dev.azure.com/checkerframework/checkerframework/_apis/build/status%2Ftypetools.jdk17u?branchName=master" alt="Azure Pipelines typetools/jdk17u status"></a></li>
    <li>Daikon: <a href="https://dev.azure.com/mernstdaikon/daikon/_build/latest?definitionId=1&branchName=master"><img src="https://dev.azure.com/mernstdaikon/daikon/_apis/build/status%2Fcodespecs.daikon?branchName=master" alt="codespecs/daikon Azure Pipelines status"></a></li>
  </ul>

  <h2 id="maven_local">Deploy to local Maven repository</h2>
  <p>
    To deploy to a <b>local</b> Maven repository, run <code>./gradlew
    PublishToMavenLocal</code> in <code>checker-framework</code>.
  </p>

  <p>
    Then, update your project's buildfile.  For Maven,
    just <a href="https://checkerframework.org/manual/#maven-locally-built">update
    the Checker Framework version number</a>.  For Gradle,
    also <a href="https://github.com/kelloggm/checkerframework-gradle-plugin#specifying-a-checker-framework-version">add <code>repositories
    { mavenLocal() }</code></a>.
  </p>

  <p>
    Often, the version number in <code>checker-framework/build.gradle</code>
    (in <code>allprojects { version ... }</code>) will end
    in <code>-SNAPSHOT</code>, but this is not a requirement.  Regardless of the
    version number, beware that you may get different results than on other
    computers that have not deployed the same commit of the Checker Framework to
    their local Maven repository.
  </p>


  <h2 id="snapshot_release">Snapshot release</h2>
  <p>To release the Maven artifacts to the Maven Central <b>snapshot</b> repository:</p>
  <ol>
    <li>
      Ensure that <code>~/.gradle/gradle.properties</code> includes your user token in <code>SONATYPE_NEXUS_USERNAME</code>
      and your user token key in <code>SONATYPE_NEXUS_PASSWORD</code>.
    </li>
    <li>
      Ensure that the version number in <code>checker-framework/build.gradle</code> (in <code>allprojects { version ... }</code>) ends in <code>-SNAPSHOT</code>.
    </li>
    <li>
      Run <code>./gradlew publish</code> in <code>checker-framework</code>.
    </li>
  </ol>

  <h3 id="using_snapshot_release">Using a snapshot release</h3>

  <h4 id="using_snapshot_release_gradle_groovy">Gradle Groovy (<code>build.gradle</code> file)</h4>

  In the <code>build.gradle</code> file of a project that you want
  to use the snapshot version of the Checker Framework:
  <pre>
repositories {
  ...
  maven {
    url 'https://central.sonatype.com/repository/maven-snapshots/'
    // Only search this repository for Checker Framework artifacts.
    content {
      includeGroup('org.checkerframework')
    }
  }
}

ext.checkerFrameworkVersion = '3.28.1-SNAPSHOT'
dependencies {
  compileOnly "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
  testCompileOnly "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
  checkerFramework "org.checkerframework:checker:${checkerFrameworkVersion}"
}
configurations.all {
  resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}</pre>

  <h4 id="using_snapshot_release_gradle_kotlin">Gradle Kotlin (<code>build.gradle.kts</code> file)</h4>

  In the <code>build.gradle.kts</code> file of a project that you want
  to use the snapshot version of the Checker Framework:

  <pre>
val checkerFrameworkVersion = "3.41.1-SNAPSHOT"
dependencies {
   compileOnly("org.checkerframework:checker-qual:${checkerFrameworkVersion}")
   testCompileOnly("org.checkerframework:checker-qual:${checkerFrameworkVersion}")
   checkerFramework("org.checkerframework:checker:${checkerFrameworkVersion}")
}
configurations.all({
   resolutionStrategy.cacheChangingModulesFor(0, "seconds")
})</pre>

  <h4 id="using_snapshot_release_maven">Maven (<code>pom.xml</code> file)</h4>

  In the <code>pom.xml</code> file of a project that you want
  to use the snapshot version of the Checker Framework:

  <pre>
    &lt;repository&gt;
      &lt;id&gt;snapshots-repo&lt;/id&gt;
      &lt;url&gt;https://central.sonatype.com/repository/maven-snapshots/s&lt;/url&gt;
      &lt;releases&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/releases&gt;
      &lt;snapshots&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;/snapshots&gt;
    &lt;/repository&gt;</pre>

  <h2 id="pre_release_checklist">Pre-release Checklist</h2>
  <p>If you have not performed a release before you must follow these steps.</p>
  <table class="table">
    <tr>
      <td>1.</td>
      <td><strong>Ensure you are a member of the types_www and pl_gang groups</strong><br/>
        Run the command "groups" on the CSE file system (perhaps on tern).
        If the group types_www or pl_gang do not appear in the list, email the appropriate
        person to be added (currently Michael Ernst).
      </td>
    </tr>
    <tr>
      <td>2.</td>
      <td><strong>Import the Checker Framework signing key for PGP</strong><br/>
        SSH into tern and run the following command:<br/>
        <code>gpg --allow-secret-key-import --import /projects/swlab1/checker-framework/hosting-info/release-private.key<br/><br/></code>
        Note:  The password for this key is located in the file<br/>
        <code>/projects/swlab1/checker-framework/hosting-info/release-private.password<br/></code>
        and is used by the release_push script to sign Maven artifacts.<br/>
      </td>
    <tr>
      <td>3.</td>
      <td><strong>Sign up for a Sonatype Account</strong><br/>
        You will likely want to do this a few days in advance.
        Directions can be found <a href="http://central.sonatype.org/pages/ossrh-guide.html">here</a>.
        Remember to be asked to be added to the org.checkerframework repository by creating
        a ticket (see the note
        <a href="http://central.sonatype.org/pages/ossrh-guide.html#create-a-ticket-with-sonatype">here</a>).
        If after signing up for a Sonatype JIRA account you are not able to sign in to
        <a href="https://issues.sonatype.org">https://issues.sonatype.org</a>
        to create a ticket, there may be a configuration problem with your account. In that case, sign up for a
        second Sonatype account, and use that account to file a ticket indicating that you cannot sign in
        with your first account.
      </td>
    </tr>
    <tr>
      <td>4.</td>
      <td><strong>Add your user token information to gradle/build.properties in your home directory.</strong><br/>
        Follow the <a href="https://central.sonatype.org/publish/generate-token/">instructions</a> to generate a user token.
        Create a <code>~/.gradle/gradle.properties</code> file with the following:
        <pre>
SONATYPE_NEXUS_USERNAME=your_tokenuser
SONATYPE_NEXUS_PASSWORD=your_tokenkey</pre>
 Since the file contains your password, make it non-readable:  <code>chmod og-rw ~/.gradle/gradle.properties</code>
      </td>
    </tr>
    <tr>
      <td>5.</td>
      <td><strong>Get edit privileges for Checker Framework</strong><br/>
        Once a release has been completed, you will be prompted to update issues in the
        issue tracker for each project that has been released.
        You will need to be a "developer" for each project so that you have update privileges for
        the issue trackers.
        You should be listed as a member of typetools as a committer on <a href="https://github.com/orgs/typetools/teams/committers">GitHub</a>.
      </td>
    </tr>
    <tr>
      <td>6.</td>
      <td><strong>Install html5validator</strong><br/>
       If you are going to perform the release on tern, you may need to install
       html5validator.  If <code>html5validator --version</code> issues any errors, try running
       <code>pip3 install --user html5validator</code>.  You may need to add <code>.local/bin</code>
       to your path.
      </td>
    </tr>
    <tr>
      <td>7.</td>
      <td><strong>Add GitHub SSH keys to tern</strong><br/>
      See <a href="https://help.github.com/articles/connecting-to-github-with-ssh/">GitHub docs</a>.
      </td>
    </tr>
    <tr>
      <td>8.</td>
      <td><strong>Configure git</strong><br/>
        <pre>
git config --global user.name "Your Name"
git config --global user.email you@example.com</pre>
        or copy over your configuration file.</td>
    </tr>
    <tr>
      <td>9.</td>
      <td><strong>Run release_build once</strong><br/>
        To save time on release day addressing potential configuration issues, before your first
        release day, ensure that <code>release_build</code> is working correctly
        by following the initial steps of the <a href="#step_by_step">Step by Step</a> section.
        <code>release_build</code> still needs to be re-run on release day (even if no changes
        were pushed to any repositories since the last run of <code>release_build</code>) in
        order for the release date to be correct in all documents.
      </td>
    </tr>
  </table>

  <h2 id="release_process_overview">Release Process Overview</h2>
  <p>This section first explains the structure of the projects on disk on tern, then lists scripts used during the release process.</p>

    <h3 id="file_layout">File Layout</h3>
    <table class="table table-bordered file_layout_table">
      <tr><th colspan="2">Release Directory <span class="glyphicon glyphicon-folder-open" style="float:right;"></span></th></tr>
      <tr>
        <td colspan="2" class="top_file">/scratch/$USER/cf-release</td>
        <td>Contains repositories and scripts to perform a release</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">build</td>
        <td>Contains repositories for:
          checker-framework, git-scripts, plume-bib, plume-scripts<br/>
          These repositories are used to build the Checker Framework and its dependencies.
        </td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">interm</td>
        <td>Contains repositories for:
          checker-framework, git-scripts, plume-bib, plume-scripts<br/>
          The repositories in build are clones of repositories in interm.  The repositories
          in interm are clones of the GitHub repositories.  This is so that
          we can test and push the release to the interm repositories then check the
          release before we have made any irreversible changes.  Then, when the release
          is validated, all we do is run &quot;git push&quot; on all of the repositories in interm.
        </td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">sanity</td>
        <td>Directory used by the release_push script to do sanity checks.
        </td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">checker-framework/docs/developer/release</td>
        <td>The directory where the release scripts are run from.  Any changes made under this directory
          won't be automatically committed when the release is committed.
        </td>
      </tr>
    </table>

    <table class="table table-bordered file_layout_table">
      <tr><th colspan="2">Live Website Directory <span class="glyphicon glyphicon-folder-open" style="float:right;"></span></th></tr>

      <tr>
        <td colspan="2" class="top_file">/cse/www2/types</td>
        <td>The file system location of the website: <br/><a href="https://checkerframework.org/">https://checkerframework.org/</a>.</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">m2-repo</td>
        <td>The location of the in-house Maven repository.  It is accessed through URL: <br/>
          <a href="https://checkerframework.org/m2-repo">https://checkerframework.org/m2-repo</a>
        </td>
      </tr>
    </table>

    <table class="table table-bordered file_layout_table">
      <tr><th colspan="2">Staging (Development) Website Directory <span class="glyphicon glyphicon-folder-open" style="float:right;"></span></th></tr>

      <tr>
        <td colspan="2" class="top_file">/cse/www2/types/dev</td>
        <td>The file system location of the development staging website: <br/><a href="https://checkerframework.org/dev/">https://checkerframework.org/dev</a>.</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">&lt;project&gt;/current</td>
        <td>The staging analogue to /cse/www2/types/&lt;project&gt;/current directory.  The latest release is copied from this directory
          to the /cse/www2/types/&lt;project&gt;/current by the release_push script after a prompt.
        </td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">m2-repo</td>
        <td>The location of the in-house staging version of the Maven repository.  It is accessed through URL: <br/>
          <a href="https://checkerframework.org/dev/m2-repo">https://checkerframework.org/dev/m2-repo</a>
        </td>
      </tr>
    </table>

    <h3 id="release_scripts">Release Scripts</h3>
    <p>As mentioned above, in order to release the Checker Framework you must run two scripts,
      release_build.py and release_push.py but there are supporting scripts and files in the
      release directory.  Some of these files are described below.
    </p>

    <table class="table table-bordered">
      <tr>
        <td>release_build.py</td>
        <td>Reverts the build/interm repositories to the state of their master repositories in GitHub.
          It then builds the projects and all their artifacts and then stages a development
          version of all websites to
          <a href="https://checkerframework.org/dev/">https://checkerframework.org/dev/</a>
          This script is thoroughly documented in code comments located in its <code>main()</code> function.
        </td>
      </tr>
      <tr>
        <td>release_push.py</td>
        <td>Verifies the release at
          <a href="https://checkerframework.org/dev/">https://checkerframework.org/dev/</a>
          is correct through scripts and manual steps.  When the user is satisfied the website
          is correct it deploys the website to the live website:
          <a href="https://checkerframework.org/">https://checkerframework.org/</a>.
          It also pushes Maven artifacts to Maven Central.
          This script is thoroughly documented in code comments located in its <code>main()</code> function.
        </td>
      </tr>
      <tr>
        <td>release_utils.py</td>
        <td>Utility methods used in both release_push and release_build.</td>
      </tr>
      <tr>
        <td>sanity_checks.py</td>
        <td>Contains methods to run various sanity checks.  These methods are called from release_push.py
        </td>
      </tr>
      <tr>
        <td>release_vars.py</td>
        <td>Global variables used in release_push, release_build, and sanity_checks.  These should NOT
          be used in release_utils as release_utils is supposed to consist of self-contained
          reusable methods.  These variables are tailored for running the scripts on
          tern.cs.washington.edu.
        </td>
      </tr>
    </table>

  <h2 id="changelog_guide">Changelog Guidelines</h2>
  <p> Each developer is responsible for updating project changelogs to reflect changes they
    have made each month.  The changelogs should be updated by "feature freeze" though at the
    latest this should be done before "code freeze".  Before releasing, the person performing
    the release will be asked to verify the changelogs.  Please check that
    there aren't typos (i.e. missing release date/version information, spelling errors, etc...).
    Also check that the changelog obeys the guidelines below.
  </p>

    <h3 id="content_guidelines">Content Guidelines</h3>
    <ul>
      <li>Only (and all) changes that affect users (including type system developers) go into the changelog.
        If a change is breaking, no matter how small, mention it.</li>
      <li>
        Even if some code has been committed to the repository, don't
        announce the feature until it has been documented in the manual.
      </li>
      <li>Checker Framework:
        <ul>
          <li>List all issues (in issue trackers) resolved since the previous release:
            <a href="https://checkerframework.org/CHANGELOG.md">previous release</a>,
            <a href="https://github.com/typetools/checker-framework/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc">issues query</a>,
            <a href="https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md">current changelog</a>.
          </li>
          <li>
            Ensure the changelogs reflect version control commits since the last release, via the
            command line:<br/>
            <code>cd $CHECKERFRAMEWORK && git log --name-status `git describe --abbrev=0 --tags`..</code><br/>
            or via <a href="https://github.com/typetools/checker-framework/commits/master">GitHub Checker Framework commit logs</a>.
          </li>
          <li>
            Ensure the changelogs reflect changes to the manual since the last release, via the
            command line:<br/>
            <code>cd $CHECKERFRAMEWORK && git diff -w `git describe --abbrev=0 --tags` docs/manual</code>
          </li>
        </ul>
      </li>

    </ul>
    <h3 id="style_guidelines">Style Guidelines</h3>
    <ul>
      <li>Changes are written from the user's perspective.  Don't include implementation details that users
        don't care about.
      </li>
      <li>To be consistent, write in the past tense (e.g. &quot;Added option for verbose error messages&quot;).</li>
      <li>Lines should not exceed 80 characters wide.</li>
      <li>Break the different programs into their own sections.  See notes on release 1.7.0 and 1.5.0 for an
        example.  Tools should have their own section within the
        Checker Framework release notes (excluding issue fixes from the issue tracker).
      </li>
      <li>Be specific.  Don't write something like "added a few options to Eclipse plugin".  Do write "added
        options to the Eclipse plugin to include stub files, ignore warnings, and show verbose output."
      </li>
    </ul>

  <h2 id="backing_out">Backing Out an Uncommitted Release</h2>
  <p>At the time of this writing, there are 2 steps that cannot be reverted.</p>
  <ol>
    <li>The push from the interm repositories to the GitHub (release) repositories</li>
    <li>The release of the staged Maven artifacts</li>
  </ol>
  <p> If you have executed either of these steps and then realized there is a breaking error, you should do another
    release.  The release script will allow you to do a point release like &quot;1.8.0.1&quot; when a version
    &quot;1.8.0&quot; already exists.<br/>
    <br/>
    If you have NOT committed an irreversible step then you can
    follow the steps below to point the live release to a previous release.  You can then redo the original
    release.  Make sure to say &quot;yes&quot; when the release script asks you to delete the old directories.
  </p>
  <h3 id="backing_out_steps">Manual Steps to Back Out a Release</h3>
  <ul>
    <li><strong>Drop the artifacts from Central</strong><br/>
      You may have staged and then closed the artifacts in the Sonatype Central Repository.  Drop (do NOT release)
      these artifacts.  See
      <a href="https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide#SonatypeOSSMavenRepositoryUsageGuide-DroppingaStagingRepository%28i.e.WhattoDoifYourStagingRepositoryHasErrors%29">
        the Sonatype OSS Repository Usage Guidelines.
      </a>
    </li>
    <!-- <li><strong>Drop the Maven Artifacts from our Maven repo *** currently unneeded ***</strong>
      <p class="alert alert-warning"><strong>Note:</strong> The procedure below is NOT recommended
        by the Maven developers guide.  However, if done carefully and quickly no harm will likely
        come.  If people end up with out-of-date artifacts, recommend to them that they use the -U option
        in Maven 3.  Never follow these instructions if the plugin release has been publicized or
        existed for a while.
      </p>

      At the moment, we have decided to drop the user of our local Maven repository in favor of using
      the Central Repository exclusively.  This may not be the case in the future.  If we do have a
      local repository, you need to go into the repositories directory (usually an m2-repo directory) and
      manually delete the versions of the Maven artifacts.  For instance, for the artifacts checker and compiler
      using version 0.9.8, I would delete the directories:
      <ul>
        <li>.../m2-repo/org/checkerframework/checker/0.9.8</li>
        <li>.../m2-repo/org/checkerframework/compiler/0.9.8</li>
      </ul>
      Furthermore, I would grep the files in the parents of these directories and ensure the version number
      does not appear in any metadata.  If so, fix up the metadata.
    </li> -->
  </ul>

  <p class="alert alert-danger"><strong>Note:</strong> You may find yourself copying release directories for some
    reason or other.  It is important to remember that the symlinks may be absolute.  You should check any
    symlinks that may be affected by the move and ensure they point to the new location and not the old one.
  </p>

  <h2 id="future_improvements">Future Improvements</h2>
  <p>Below is a roughly priority-ordered list of future improvements.  In a perfect world we would do
    all of these.  At the moment, I believe only the first 2 (Open JDK Javadoc Fixes,
    and More Sanity Checks) should have any appreciable priority.
  </p>

    <h3 id="future_more_sanity_checks">More Sanity Checks</h3> <!-- omit from toc -->
    There are likely more sanity checks we might want to run during the release process.  One such example
    would be running the tutorial from the command line.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Implement one of the sanity checks mentioned in this section.</li>
      <li>Add your sanity check to the appropriate location in the release_push script.</li>
      <li>Update this document to reflect the new steps.</li>
    </ul>
    <h4 id="sanity-checks">Sanity Checks:</h4> <!-- omit from toc -->
    <ul>
      <li>Run tutorial sanity check automatically via command line.</li>
    </ul>
    <h3 id="future_continuous_integration">Release in Continuous Integration</h3> <!-- omit from toc -->
    If we could run the release_build script nightly, we could head off broken links and other
    release related errors.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Create a tern task to run the release_build script without prompting.</li>
      <li>Observe the output of this task and identify possible errors.</li>
      <li>Fix up all observed errors until the release_build script runs without error.</li>
      <li>We probably want to move the link checking of the development site to the release_build script and
        write it out to disk.  This will allow the developer releasing the framework to consult pre-made
        link-checking results rather than waiting for the link checker to execute in the push script.
      </li>
    </ul>
    <h3 id="future_auto-copy_release_scripts">Auto-copy Release Scripts</h3> <!-- omit from toc -->
    The first step in running the release process, after the pre-release checklist, is to copy the
    release scripts into the <code>cf-release</code> directory.  We could automate this.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Create a read-only script in cf-release/scripts.</li>
      <li>Edit the script so that it downloads all release scripts into the cf-release directory.</li>
      <li>Update this document to reflect this new process.</li>
    </ul>
    <h3 id="future_option_parsing">Option Parsing</h3> <!-- omit from toc -->
    There is currently some primitive option parsing written into the release scripts.  We should use
    Python's built-in option parsing library.  There are multiple built-in libraries.  Please use the latest one.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Look up the latest Python parsing library.</li>
      <li>Replace the option parsing in the release_build.py and release_push.py scripts with library calls.</li>
    </ul>
    <h3 id="future_option_projects">Optional Projects</h3> <!-- omit from toc -->
    A user might want to test the release_build script only on a specific project.  Some work has gone into
    the ability to select a project to build.  However, this currently doesn't take into consideration of dependencies.
    It might be more hassle than it's worth to implement this feature.  We should either complete the implementation
    or remove the partial implementation that already exists.  See <a href="#future_repl_mode">REPL Mode</a>.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Improve option parsing to allow the user to select only certain projects to build.</li>
      <li>Improve scripts to resolve dependencies between projects and only build the selected projects and
        their dependencies.
      </li>
    </ul>
    <h3 id="future_repl_mode">REPL Mode</h3> <!-- omit from toc -->
    The current script is built in an imperative style with little use of object orientation.  This improvement
    would create methods or objects that further encapsulate the current set of steps.  We could then provide
    an easy way to execute these steps from the Python REPL.  This would allow the user to execute individual steps
    in whatever order they saw fit from the Python REPL.  This could also be used to
    automatically back out the current release or the ability to edit/debug the release steps more easily.
    <h4>Tasks:</h4> <!-- omit from toc -->
    <ul>
      <li>Further separate the steps of the release process.</li>
      <li>Provide a default parameterization for these steps to make them easily runnable from the
        command line. </li>
      <li>Provide a script to launch Python with these commands on its path.</li>
      <li>Update this README to document the new functionality.</li>
    </ul>
</div>
</div>
</div>

</body>
</html>

<!--  LocalWords:  serif px pre CCC JDK AFS PAG mkdir cd svn co EFEFEF ul li Changelog stubparser JavaParser GenericAnnotatedTypeFactory CFTransfer CFAbstractTransfer CFAbstractAnalysis CFAnalysis CFAbstractStore CFStore CFAbstractValue CFValue BaseTypeVisitor BaseTypeChecker SourceChecker MultigraphQualifierHierarchy AbstractQualifierPolymorphism AnnotationUtils TreeAnnotator TODO typetools SDK BOM includeGroup 'org checkerFrameworkVersion compileOnly testCompileOnly checkerFramework resolutionStrategy cacheChangingModulesFor tokenuser tokenkey
 -->
<!--  LocalWords:  xml ver dev yyyyMMDD URL url diff buildfile kelloggm checkerframework gradle
 -->
<!--  LocalWords:  HandlerUtil macOS typecheck www Sonatype typetests html5validator config interm
 -->
<!--  LocalWords:  Hevea TEXINPUTS m2 repo py aren changelog changelogs utils OSS symlinks doesn
 -->
